﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Linq;
using System.IO;
using System.Linq;
using System.Text;
using CI.Models.Data;
using log4net;

namespace XmlModelPackager
{
    public class ProductionXmlGenerator : XmlGeneratorBase, IXmlGenerator
    {
        private readonly ILog _logger = LogManager.GetLogger(typeof (ProductionXmlGenerator));
        private List<int> _groupsToLoadAttributes = new List<int>(1027);

        public ProductionXmlGenerator()
            : base(new FileInfo("production.xml"), "Production")
        {
        }

        protected TyrannisDataContext GetDataContext()
        {
            return new TyrannisDataContext(ConfigurationManager.ConnectionStrings["TyrannisDB"].ConnectionString);
        }

        public void GenerateXml()
        {

            using (var ctx = GetDataContext())
            {
                var items = ctx.invTypes.Where(i => i.published!=null && i.published.Value == true);

                foreach(var item in items)
                {
                    _logger.DebugFormat("Processing {0}:{1}",item.typeID,item.typeName);

                    BeginElement("Item");

                    invType cItem = item;

                    WriteAttributes(cItem, "typeID", "groupID","typeName","description","graphicID","volume","capacity","portionSize","raceID","basePrice","published","marketGroupID");

                    WriteBlueprint(ctx, item);
                    WriteSchematic(ctx, item);
                    WriteMaterials(ctx, cItem);

                    EndElement();
                }
            }
        }

        private void WriteSchematic(TyrannisDataContext ctx, invType item)
        {
            var outputs = ctx.planetSchematicsTypeMaps.Where(p => p.typeID == item.typeID && !p.isInput.Value);
            planetSchematicsTypeMap output = null;

            if (outputs.Count() > 1)
            {
                foreach (var piOutput in outputs)
                {
                    var schematic = ctx.planetSchematics.Where(p => p.schematicID == piOutput.schematicID).FirstOrDefault();

                    if (schematic != null)
                    {
                        output = piOutput;
                        break;
                    }
                }
            }
            else output = outputs.FirstOrDefault();

            if (output!=null)
            {
                var schematic = ctx.planetSchematics.Where(p => p.schematicID == output.schematicID).FirstOrDefault();

                if (schematic!=null)
                {
                    var inputs =
                        ctx.planetSchematicsTypeMaps.Where(
                            p => p.schematicID == schematic.schematicID && p.isInput.Value);

                    foreach(var input in inputs)
                    {
                        BeginElement("Material");
                        WriteAttribute(input.typeID, "materialTypeID");
                        WriteAttribute(input.quantity, "quantity");
                        EndElement();
                    }

                    BeginElement("Schematic");
                    WriteAttributes(schematic, "schematicID", "schematicName", "cycleTime");
                    WriteAttribute(output.quantity, "outputQuantity");

                    var pins = ctx.planetSchematicsPinMaps.Where(p => p.schematicID == schematic.schematicID);

                    foreach(var pin in pins)
                    {
                        BeginElement("PIN");
                        WriteAttribute(pin.pinTypeID, "typeID");
                        EndElement();
                    }

                    EndElement();
                }
            }
        }

        private static KeyValuePair<string, string> Key(string src, string dst)
        {
            return new KeyValuePair<string, string>(src, dst);
        }

        private void WriteBlueprint(TyrannisDataContext ctx, invType item)
        {
            var bp = ctx.invBlueprintTypes.Where(b => b.productTypeID == item.typeID).FirstOrDefault();

            if (bp!=null)
            {
                BeginElement("Blueprint");

                WriteAttributes(bp, "productionTime", "techLevel","researchProductivityTime","researchMaterialTime","researchCopyTime","researchTechTime","productivityModifier","wasteFactor","maxProductionLimit");

                WriteBlueprintRAM(ctx, bp);

                EndElement();
            }
        }

        private void WriteBlueprintRAM(TyrannisDataContext ctx, invBlueprintType bp)
        {
            var rams = ctx.ramTypeRequirements.Where(r => r.typeID == bp.blueprintTypeID);

            foreach(var ram in rams)
            {
                BeginElement("RAM");
                WriteAttributes(ram, "activityID","damagePerJob","quantity","recycle","requiredTypeID");
                EndElement();
            }
        }

        private void WriteMaterials(TyrannisDataContext ctx, invType cItem)
        {
            var materials = ctx.invTypeMaterials.Where(m => m.typeID == cItem.typeID);

            foreach(var material in materials)
            {
                BeginElement("Material");

                WriteAttributes(material, "materialTypeID", "quantity");

                EndElement();
            }
        }
    }
}
